home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
comm
/
tlx_sq15.zip
/
PSHDIR1A.ZIP
/
PUSHDIR.ASM
< prev
next >
Wrap
Assembly Source File
|
1988-12-22
|
8KB
|
249 lines
main group code
code segment public para 'code'
assume cs:main
org 100h ;.COM file
BEGIN: jmp START ;program starts here
; db "Copyright 1986 Ziff-Davis Publishing Co.",1Ah
; Changes made on 12/22/88 by Mike Williams
; 1. Support command line parm to also CHDIR
; 2. If path string refers to a drive, log that drive
;
signature db 'PUSHDIR VERSION 1.a'
lengthsignature = $ - signature
savedint16 dd ? ;old int 16h vector
nextpush dw offset main:push1dir ;next place to save a dir
push1dir db 67 dup (0) ;storage for a saved dir
push2dir db 67 dup (0) ;more storage
push3dir db 67 dup (0) ;more storage
push4dir db 67 dup (0) ;more storage
push5dir db 67 dup (0) ;more storage
push6dir db 67 dup (0) ;last storage
;up to here must be EXACTLY identical in both PUSHDIR and POPDIR so that
;popdir can know how to access the memory space reserved by the first
;pushdir.
;myint16 is an interrupt handler chained onto the existing interrupt handler.
;it is used to find out if PUSHDIR is already installed and if it is, where
;is it located? It works by adding another function to int 16h. To use it
;ax = 7788h, bx = 7789h, and ds:si points to the signature string. If any one
;of these conditions is not true, then the int 16h call is passed onto the
;old routine without doing anything. If they are all true, then we switch
;ax and bx and return ds = code segment (cs) of the interrupt handler.
myint16 proc far
pushf ;save flags
cmp ax,7788h ;possible signature request ?
je CHECKSIG ;yes
NOTSIG:
popf ;no - recover flags
jmp cs:[savedint16] ;go to old routine as normal
CHECKSIG:
cmp bx,7789h ;possible signature request ?
jne NOTSIG ;no
;ax and bx were correct for a signature request
;now see if ds:si was pointing to the signature string
;the whole idea of the signature is that is has to be
;totally unique so no other program could possibly use the same one.
push es ;save the registers we will use
push di
push cx
mov di,offset main:signature ;address of the signature
mov cx,lengthsignature ;length of the signature
repe cmpsb ;does string at ds:si match es:di ?
pop cx ;recover all registers we used
pop di
pop es
jne NOTSIG ;no, not correct signature
;yes, it was a signature request so return ds equal to the current code
;segment so subsequent pushdir's and popdir's know where the original
;is located.
push cs
pop ds ;set ds = cs
xchg ax,bx ;flip these two so we know that
;ds is being returned
popf ;recover original flags
iret ;return back to the program
;that called the int 16h
myint16 endp
endresident label byte ;label marking the end of the
;code to remain resident
;code after here will not remain resident
install db 1 ;0 = already installed, 1 = not installed
abortmsg db 'Error reading the current directory.$'
installmsg db 'PUSHDIR 1.a installed.$'
START:
sti ;turn interrupts on
;first check to see if PUSHDIR is already installed
mov ax,7788h ;signature request
mov bx,7789h ;signature request
mov si,offset main:signature ;point to signature
int 16h ;is it installed ?
assume ds:nothing
cmp bx,7788h ;were ax and bx switched ?
jne NOTINSTALLED ;no
cmp ax,7789h ;were ax and bx switched ?
jne NOTINSTALLED ;no
;yes it is installed already
mov cs:[install],0 ;don't install it again
NOTINSTALLED:
;ds = segment of the installation
;store the current directory, including disk drive letter
mov si,ds:[nextpush] ;get storage address for next push
add si,3 ;make room for d:\
mov dl,0 ;default drive
mov ah,47h ;dos function number
int 21h ;get current directory
jc ABORTERR ;error message if carry set
mov ah,19h ;dos function number
int 21h ;get the current drive
add al,'A' ;convert to ascii
mov byte ptr ds:[si-3],al ;add the "D:\" in front of path
mov byte ptr ds:[si-2],':'
mov byte ptr ds:[si-1],'\'
;now update [nextpush] for the next PUSHDIR
cmp ds:[nextpush],offset main:push6dir ;time to wrap around ?
je WRAPPUSH ;yes
add ds:[nextpush],67 ;no, point to next one
jmp short GOTNEXTPUSH
WRAPPUSH:
mov ds:[nextpush],offset main:push1dir ;wrap back to beginning
GOTNEXTPUSH:
;-----------------------------------------------------------------------------
;
; This block of code was added on 12/22/88 by Mike Williams
; to support a command line parm to change directories
; and (if necessary) select a new default drive.
;
;-----------------------------------------------------------------------------
; look at psp command tail for directory parm
; and call change directory function
push ds
push cs
pop ds ;ensure ds is good
mov bl,ds:[0080h] ;length of parm in psp
;command tail
sub bh,bh
add bx,0081h ;add start addr to length
mov byte ptr [bx],00h ;string terminator
mov si,0081h ;point to beginning of string
CHDLOOP: ;string is pointed to by ds:si
lodsb ;look for first non-blank
cmp al,20h ;blank?
je CHDLOOP ;yes, try again
dec si ;si got incremented in lodsb
mov dx,si ;pointer to parm
mov ah,3bh ;function call to CHDIR
int 21h ;DOS function call
;now check for the presence of a drive designator on the
;path string and if present set the requested drive also
mov bl,ds:[si+1] ;pickup second char in parm
cmp bl,':' ;is it a colon: ?
jne AROUND ;no , go around this code
;yes
mov dl,ds:[si] ;get drive letter from path
and dl,0dfh ;convert to uppercase letter
sub dl,'A' ;convert to binary (0=A, 1=B)
mov ah,0eh ;dos function to select drive
int 21h ;set drive
AROUND:
pop ds ;restore ds
;--------------------------end of 12/22/88 change-----------------------------
cmp cs:[install],1 ;should we install it
je DOINSTALL ;yes
int 20h ;no, we are done
ABORTERR:
mov dx,offset main:abortmsg ;address of error message
mov ah,9 ;dos function number
int 21h ;show error message
int 20h ;end program on error
;if we got to here, then pushdir is not already installed,
;so we need to install it by making part of it memory resident.
DOINSTALL:
push cs
pop ds ;set ds = cs
assume ds:main
;save the current int 16h vector
push es ;save es
mov ax,3516h ;dos function 35h, vector 16h
int 21h ;get the existing vector into es:bx
mov word ptr [savedint16],bx ;save es:bx
mov word ptr [savedint16+2],es ;save es:bx
pop es ;recover es
;now set the new int 16h vector to point to my routine
mov dx,offset main:myint16 ;point to my new routine
mov ax,2516h ;dos function 25h, vector 16h
int 21h ;set new vector to ds:dx
;now show a message on the screen
;this message can be suppressed by redirecting output to NUL
;by using pushdir like this: PUSHDIR >NUL
mov dx,offset main:installmsg
mov ah,9
int 21h ;show installation message
;now free up the memory occupied by the envirnoment so it is not
;permanently wasted
mov ax,ds:[2ch] ;get segment of environment
mov es,ax ;load envirnoment segment into es
mov ah,49h ;dos function number
int 21h ;free the environment memory
;now terminate resident protecting only the first part of this program
mov dx,offset main:endresident ;point to end of resident code
add dx,0fh ;round up
mov cl,4
shr dx,cl